//global vars
var selectedElement=null;
var bCleanPaste=true;
var moz_prevent_copy=false;

// Dialogos
var dialogs_features=""; //"menubar=no,titlebar=no,toolbar=no,resizable=no,width=560,height=300,top=0,left=0";

Object.extend(String.prototype, {
  insert_at: function(text, pos) {
    return(this.substr(0,pos)+text+this.substring(pos,this.length));
  }
});

Object.extend(Element, {
  handleNodes: function(node) {
    node = $(node);
    var name = node.nodeName.toLowerCase();

    switch(name){
      case "p":
        this.cleanWhitespace(node);
        var descendants = $A(this.childNodes);
        if(descendants.length>1 && descendants.last().nodeName.toLowerCase()=="br") {
            descendants.last().remove();
        } else {
          var content = node.innerHTML;
          if(content ? content.blank() : false)
            node.innerHTML = '<br>';
        }
        break;
    }
  },

  handleAttributes: function(node) {
    if(node.hasAttributes()) this.cleanAttributes(node);
    if(node.hasChildNodes()){
      var nodes=node.childNodes;
      for(var x=0;x<nodes.length;x++){this.handleAttributes(nodes.item(x));}
    }
  },

  cleanAttributes: function(node) {
    var nodeName=node.nodeName.toLowerCase();

    node.removeAttribute("align");
    node.removeAttribute("background");
    node.removeAttribute("bgcolor");
    node.removeAttribute("border");
    node.removeAttribute("color");
    node.removeAttribute("face");
    node.removeAttribute("noshade");
    node.removeAttribute("nowrap");
    node.removeAttribute("style");
    node.removeAttribute("valign");
    node.removeAttribute("vlink");

    switch(nodeName){
      case "table":
        node.removeAttribute("width");
        node.removeAttribute("height");
      break;
    }
  }
});

/* FUNCIONES */
function getUniqueId(){
  var now=new Date();
  return("wym-"+now.getTime());
}

//declaring the class
var Editor = Class.create();

Object.extend(Editor.prototype, {
  initialize: function(textarea) {
    this.textarea = $(textarea);
    this.textarea.observe('keyup',this.getHTML);
    this.iframe = $('iframe_editor');
    this.editor = (Prototype.Browser.IE)?$('editor'):$(this.iframe.contentDocument.body);
    if (Prototype.Browser.IE) {
      this.editor.observe('keyup', this.saveCaret.bindAsEventListener(this));
      this.editor.observe('click', this.saveCaret.bindAsEventListener(this));
    }
    this.start();
  },

  start: function() {
    if (Prototype.Browser.Gecko) {
      ed=this.iframe.contentWindow.parent.$('editor');
      if(ed && this.iframe.contentDocument) this.iframe.contentDocument.body.innerHTML=ed.innerHTML;

      if (this.iframe.contentDocument) this.iframe.contentDocument.designMode="on";

      $A(this.editor.childNodes).each(function(node) {
        Element.handleNodes(node);
        Element.handleAttributes(node);
      });

      this.iframe.contentDocument.addEventListener('keydown',this.iframe_keydown_handler.bindAsEventListener(this),false);
      this.iframe.contentDocument.addEventListener('keyup',this.iframe_keyup_handler.bindAsEventListener(this),false);

      this.execCom("styleWithCSS",false);
    }
    this.getHTML();
    this.resizeIframe();
  },

  getHTML: function() {
    this.textarea.innerText = this.editor.innerHTML;
  },

  execCom: function (cmd,opt){
  if (Prototype.Browser.Gecko) {
    switch(cmd.toLowerCase()) {
      case "bold":
        container=this.getSelectedContainer();
        if(container.tagName.toLowerCase()=="strong") {
          ntext=this.iframe.contentDocument.createTextNode(container.innerHTML);
          container.parentNode.replaceChild(ntext,container);
        }
        else this.iframe.contentDocument.execCommand(cmd,'',opt);
        break;
      case "italic":
        container=this.getSelectedContainer();
        if(container.tagName.toLowerCase()=="em") {
          ntext=this.iframe.contentDocument.createTextNode(container.innerHTML);
          container.parentNode.replaceChild(ntext,container);
        }
        else this.iframe.contentDocument.execCommand(cmd,'',opt);
        break;
      case "indent": case "outdent":
        var focusNode=this.getSelectedNode("focus");
        var anchorNode=this.getSelectedNode("anchor");

        focusNode=this.getFirstBlockParent(focusNode);
        anchorNode=this.getFirstBlockParent(anchorNode);

        if(focusNode!=null && focusNode==anchorNode && focusNode.tagName.toLowerCase()=="li") {
          var ancestor=focusNode.parentNode.parentNode;
          if(focusNode.parentNode.childNodes.length >= 1 || ancestor.tagName.toLowerCase()=="ol"
          	|| ancestor.tagName.toLowerCase()=="ul")

            this.iframe.contentDocument.execCommand(cmd,'',opt);
        }
        break;
      default:
        this.iframe.contentDocument.execCommand(cmd,'',opt);
        break;
    }
  } else if(Prototype.Browser.IE) {
    switch(cmd.toLowerCase()) {
      case "indent": case "outdent":
        container=this.getSelectedContainer();
        if(container.tagName.toLowerCase()=="li") document.execCommand(cmd);
        break;
      default:
        document.execCommand(cmd);
        break;
    }
  }

    this.preCleanHTML();
  },

  saveCaret: function() {
    this.caretPos = document.selection.createRange();
    this.resizeIframe();
  },

  getSelectedContainer: function () {
    if(selectedElement==null) {
      if(Prototype.Browser.IE) {
          if (this.caretPos != null)
          if(this.caretPos.parentElement != "undefined") return(this.caretPos.parentElement());
        } else {
        var sel= this.iframe.contentWindow.getSelection();
        var node=sel.focusNode;
        if(node.nodeName=="#text")return(Element.extend(node.parentNode));
        else return(Element.extend(node));

      }
    } else return(selectedElement);
  },

  getSelectedNode: function(sType){
      var sel=this.iframe.contentWindow.getSelection();
      if(sType=="focus") node=sel.focusNode;
      else if(sType=="anchor") node=sel.anchorNode;
      Element.extend(node);
      if(node.nodeName=="#text")return(node.parentNode);
      else return(node);
  },

  isBlock: function(elem) {
    switch($(elem).tagName.toLowerCase()) {
      case "address": case "blockquote": case "div": case "dl": case "fieldset":  case "form":case "h1": case "h2": case "h3": case "h4": case "h5": case "h6":case "hr": case "noscript": case "ol": case "p": case "pre": case "table": case "ul": case "dd": case "dt": case "li": case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr":
        return(true);
        break;
      default:
        return(false);
        break;
    }
  },

  getFirstBlockParent: function (elem) {
    elem = $(elem);
    if(elem) {
      if(this.isBlock(elem)) return elem;
      else return elem.ancestors.find(isBlock);
    }
    else return(null);
  },

  preCleanHTML: function() {
    if (Prototype.Browser.IE) {
      this.textarea.innerText="";
      this.textarea.innerText = this.getCleanHTML();
    } else {
      this.textarea.value = "";
      $A(this.editor.childNodes).each(function(node) {
        Element.handleNodes(node);
        Element.handleAttributes(node);
      });
      this.textarea.value = this.getCleanHTML();
    }

  },

  getCleanHTML: function () {
    var sHtml = this.editor.innerHTML;
    var flagTag=false,begTag=false;
    var tag="",ret="",attr="";
    var level=0;

    for(var x=0;x<sHtml.length;x++) {
      c=sHtml.charAt(x);

      if(begTag) {
        if(c==" " || c==">") {
          switch(tag) {
            case "b": tag="strong"; break;
            case "/b": tag="/strong"; break;
            case "i": tag="em"; break;
            case "/i": tag="/em"; break;
            case "br": tag="br /"; break;
            case "ol": case "ul":
              level++;
              if(level>1 && ret.substr(ret.length-5)=="</li>")
                ret=ret.substr(0,ret.length-5);
              break;
            default:
              break;
          }
          begTag=false;
        }
        else tag+=c;
      }

      if(c=="<"){begTag=true;flagTag=true;}

      if(flagTag) {
        if(c==">") {
          flagTag=false;
          switch(tag) {
            case "img": case "hr": case "input": case "link": case "base": case "basefont": case "col": case "frame": case "isindex": case "meta":case "param":
              ret+="<"+tag+attr+"/>";
            break;
            case "/ol": case "/ul":
              if(level>1)ret+="<"+tag+attr+"></li>";
              else ret+="<"+tag+attr+">";
              level--;
              break;
            default:
              ret+="<"+tag+attr+">";
              break;
          }

          tag="";
          attr="";
        } else if(!begTag){
          attr+=c;
        }
      } else ret+=c;
    }
    return(ret);
  },

  getContainerOfTypeArray: function (elem,aContainerTypes) {
    var bFound=false;
    if(elem!=null && elem.id!="editor") {
      for(i=0;i<aContainerTypes.length;i++) {
        if(elem.tagName==aContainerTypes[i]) {
          bFound=true;
          break;
        }
      }
      if(!bFound) {
        elem=elem.parentNode;
        return(this.getContainerOfTypeArray(elem,aContainerTypes));
      } else return(elem);
    }else return(null);
  },

  getContainerOfType: function (elem,sContainerType) {
    if(elem!=null && elem.id!="editor") {
      if(elem.tagName!=sContainerType) {
        elem=elem.parentNode;
        return(this.getContainerOfType(elem,sContainerType));
      } else return(elem);
    }else return(null);
  },

  setContainer: function(sType) {
    container=this.getSelectedContainer();
    if(container!=null) {
      switch(container.tagName){
        case "P": case "H1": case "H2": case "H3": case "H4": case "H5": case "H6": case "PRE": case "BLOCKQUOTE":  break;
        default:
          var aTypes=new Array("P","H1","H2","H3","H4","H5","H6","PRE","BLOCKQUOTE");
          container=this.getContainerOfTypeArray(container,aTypes);
          break;
      }

      if(container!=null) {
        var newNode=null;
        if(sType.toLowerCase()=="blockquote"){
          var blockquote=this.getContainerOfType(container,"BLOCKQUOTE");
          this.resizeIframe(80);
          if(blockquote==null) {
            newNode=document.createElement(sType);
            container.parentNode.insertBefore(newNode,container);
            newNode.appendChild(container);
          } else {
            var nodes=blockquote.childNodes;
            var lgt=nodes.length;
            for(var x=0;x<lgt;x++) {
              blockquote.parentNode.insertBefore(nodes.item(0),blockquote);
            }
            blockquote.parentNode.removeChild(blockquote);
          }
        } else {
          newNode=document.createElement(sType);
          var html=container.innerHTML;
          DOM.replaceElement(container,newNode);
          newNode.innerHTML=html;
        }
      }
    }
      //this.preCleanHTML();
  },

  removeClassAttr: function () {
    var container=this.getSelectedContainer();
    if(container) {
      Element.extend(container).className = false;
    }
  },

  displayClasses: function(){

  },

  openDialog: function (sUrl){
    this.dialog=window.open(sUrl,"dialog",dialogs_features);
  },

  iframe_keydown_handler: function(evt) {
    if(evt.keyCode==86 && evt.ctrlKey) if(moz_prevent_copy) evt.preventDefault();
  },

  iframe_keyup_handler: function(evt) {
    this.resizeIframe();
    if(evt.keyCode==13 && !evt.shiftKey) {
      nodes = this.editor.childNodes;
      for(var x=0;x<nodes.length;x++){
        if(nodes.item(x).nodeName.toLowerCase()=="br") this.editor.removeChild(nodes.item(x));
      }
    } else if(evt.keyCode!=8 && evt.keyCode!=46 && evt.keyCode!=17 && !evt.ctrlKey) {
      container=this.getSelectedContainer();
      name=container.tagName.toLowerCase();
      if( name=="strong" || name=="b" || name=="em" || name=="i" || name=="sub" || name=="sup" || name=="a") 
        name=container.parentNode.tagName.toLowerCase();
      if(name=="body") this.execCom("formatblock","P");
    }
    this.displayClasses();
  },

  iframe_mouseup_handler: function(evt) { },

  htmlVisible: function() {
    this.textarea.toggle();
  },

  resizeIframe: function( pixels ) {
    pixels = pixels || 50;
    $('iframe_editor').setStyle({overflow:'auto', height:($('iframe_editor').contentWindow.document.body.scrollHeight + pixels)+"px"});
  },
});

//var myTalker = new editor('hi there.');
//myTalker.showMessage(); //displays alert
window.onload = function() {
  wym = new Editor('txthtml');
};


Event.addBehavior({
  '#block_selector:change' : function() {
    wym.setContainer(this.value.toUpperCase());
  },
  '#block_selector, #block_selector:blur' : function() {
    this.cleanWhitespace().firstChild.selected=true;
  },
  // Definir un atributo del que coger el comando y tratar todos los #m_basic a:click igual
  '#m_basic a#strong:click' : function() {
    wym.execCom('Bold');
  },
  '#m_basic a#italic:click' : function() {
    wym.execCom('Italic');
  },
  '#m_basic a#sup:click' : function() {
    wym.execCom('Superscript');
  },
  '#m_basic a#sub:click' : function() {
    wym.execCom('Subscript');
  },
  '#m_basic a#ordered_list:click' : function() {
    wym.removeClassAttr(); wym.execCom('InsertOrderedList');
  },
  '#m_basic a#unordered_list:click' : function() {
    wym.removeClassAttr(); wym.execCom('InsertUnorderedList');
  },
  '#m_basic a#indent:click' : function() {
    wym.execCom('Indent');
  },
  '#m_basic a#outdent:click' : function() {
    wym.execCom('Outdent');
  },
  '#m_basic a#undo:click' : function() {
    wym.execCom('Undo');
  },
  '#m_basic a#redo:click' : function() {
    wym.execCom('Redo');
  },
  '#html:click' : function() {
    wym.htmlVisible();
  }
});
